package com.tiancheng.trade.settlement.service.settlement.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.tiancheng.trade.commom.core.data.PageInfo;
import com.tiancheng.trade.commom.core.data.Result;
import com.tiancheng.trade.settlement.bo.MerchantBO;
import com.tiancheng.trade.settlement.enums.InvoiceTypeEnum;
import com.tiancheng.trade.settlement.enums.SettlementTypeEnum;
import com.tiancheng.trade.settlement.exception.BusinessException;
import com.tiancheng.trade.settlement.feign.MerchantPaymentChannelService;
import com.tiancheng.trade.settlement.mapper.settlement.OrderSourceCostMapper;
import com.tiancheng.trade.settlement.model.settlement.OrderSourceCost;
import com.tiancheng.trade.settlement.service.settlement.IOrderSourceCostService;
import com.tiancheng.trade.settlement.util.ExcelUtil;
import com.tiancheng.trade.settlement.util.ObjectConvertUtil;
import com.tiancheng.trade.settlement.vo.settlement.admin.res.OrderSourceResVO;
import com.tiancheng.trade.settlement.vo.settlement.api.GetOrderSourceCostVO;
import com.tiancheng.trade.settlement.vo.settlement.export.OrderSourceCostExportVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OrderSourceCostService implements IOrderSourceCostService {

    @Autowired
    private OrderSourceCostMapper costMapper;

    @Autowired
    MerchantPaymentChannelService merchantService;

    /**
     * 1酒店 3门票 4线路
     *
     * @param orderSource
     * @return
     * @throws BusinessException
     */
    @Override
    public PageInfo<OrderSourceCost> getOrderSourceCostList(GetOrderSourceCostVO orderSource) throws BusinessException {
        QueryWrapper<OrderSourceCost> conditions = new QueryWrapper<OrderSourceCost>();
        conditions.eq("is_delete", "0");
        if (StringUtils.isNotEmpty(orderSource.getDate())) {
            conditions.eq("verified_time", orderSource.getDate().replace("-", ""));
        }
        if (StringUtils.isNotEmpty(orderSource.getOrderSource())) {
            conditions.eq("order_source", orderSource.getOrderSource());
        }
        PageInfo<OrderSourceCost> list = costMapper.find(conditions, orderSource.getCurrentPage(), orderSource.getPageSize());
        if (CollectionUtils.isNotEmpty(list.getList())) {
            convertSourceCostList(list.getList());
        }
        return list;
    }

    private void convertSourceCostList(List<OrderSourceCost> list) {
        BigDecimal bigNum = new BigDecimal("100");
        list.forEach(a -> {
            a.setSettlementType(SettlementTypeEnum.getDesc(a.getSettlementType()));
            a.setInvoiceType(InvoiceTypeEnum.getDesc(a.getInvoiceType()));
            if (null != a.getSellPrice()) {
                BigDecimal num = new BigDecimal(a.getSellPrice());
                a.setSellPriceStr(num.divide(bigNum).toString());
            }
            if (null != a.getProcessCost()) {
                BigDecimal num = new BigDecimal(a.getProcessCost());
                a.setProcessCostStr(num.divide(bigNum).toString());
            }
            if (null != a.getCostPrice()) {
                BigDecimal num = new BigDecimal(a.getCostPrice());
                a.setCostPriceStr(num.divide(bigNum).toString());
            }
            if (null != a.getPlatService()) {
                BigDecimal num = new BigDecimal(a.getPlatService());
                a.setPlatServiceStr(num.divide(bigNum).toString());
            }
            if (null != a.getNoTaxCost()) {
                BigDecimal num = new BigDecimal(a.getNoTaxCost());
                a.setNoTaxCostStr(num.divide(bigNum).toString());
            }
            if (null != a.getTaxAmount()) {
                BigDecimal num = new BigDecimal(a.getTaxAmount());
                a.setTaxAmountStr(num.divide(bigNum).toString());
            }

        });
    }


    @Override
    public int updateOrderSourceCost(String date, String orderSource) throws BusinessException {
        List<OrderSourceResVO> list = costMapper.getOrderSourceCostList(date, orderSource);
        if (CollectionUtils.isNotEmpty(list)) {
            costMapper.deleteOrderSourceCost(date.replace("-", ""), orderSource);
            List<OrderSourceCost> sourceCostList = convertOrderSourceCost(list);
            if (CollectionUtils.isNotEmpty(sourceCostList)) {
                return costMapper.addOrderSourceCost(sourceCostList);
            }
        }
        return 0;
    }

    @Override
    public int addOrderSourceCost(String date, String orderSource) throws BusinessException {
        List<OrderSourceResVO> list = costMapper.getOrderSourceCostList(date, orderSource);
        if (CollectionUtils.isNotEmpty(list)) {
            List<OrderSourceCost> sourceCostList = convertOrderSourceCost(list);
            if (CollectionUtils.isNotEmpty(sourceCostList)) {
                return costMapper.addOrderSourceCost(sourceCostList);
            }
        }
        return 0;
    }

    private List<OrderSourceCost> convertOrderSourceCost(List<OrderSourceResVO> list) {

        List<OrderSourceCost> sourceCostList = new ArrayList<OrderSourceCost>();
        //获取商户编号集合
        List<String> listStr = list.stream().map(OrderSourceResVO::getMerchantCode).collect(Collectors.toList());
        //按商户取商户城市信息
        List<String> listStr1 = listStr.stream().distinct().collect(Collectors.toList());
        Result<List<MerchantBO>> merchantBOList = merchantService.getMerchantByMerCode(listStr1);
        Map<String, MerchantBO> merchantMap = new HashMap<String, MerchantBO>();
        if (merchantBOList.getRet() == 0) {
            List<MerchantBO> merchantList = merchantBOList.getData();
            merchantMap = merchantList.stream().collect(Collectors.toMap(MerchantBO::getMerchantCode, Function.identity(), (k1, k2) -> k2));
        }
        BigDecimal num = new BigDecimal(100);

        for (OrderSourceResVO orderSource : list) {
            OrderSourceCost sourceCost = ObjectConvertUtil.convert(orderSource, OrderSourceCost.class).get();

            if (null != merchantMap) {
                MerchantBO merchantBO = merchantMap.get(orderSource.getMerchantCode());
                sourceCost.setCityName(merchantBO == null ? "" : merchantBO.getCityName());
            }
            sourceCost.setVerifiedTime(orderSource.getVerifiedTime().replace("-", ""));
            sourceCost.setSellPrice(orderSource.getVerifiedAmount() - orderSource.getRefundAmount());
            sourceCost.setProcessCost(orderSource.getProcessCost());
            sourceCost.setCostPrice(orderSource.getCostPrice());
            if (SettlementTypeEnum.SELF.getCode().equals(orderSource.getSettlementType())) {
                sourceCost.setPlatService(0);
            } else {
                sourceCost.setPlatService(sourceCost.getSellPrice() - sourceCost.getCostPrice());
            }
            BigDecimal rate = orderSource.getTaxRate().add(num).divide(num);
            BigDecimal costPrice = new BigDecimal(orderSource.getCostPrice().toString());
            BigDecimal noTaxCost = costPrice.divide(rate, 2, BigDecimal.ROUND_UP);
            sourceCost.setNoTaxCost(noTaxCost.setScale(0, BigDecimal.ROUND_HALF_UP).intValue());
            BigDecimal taxAmount = costPrice.divide(rate, 1, BigDecimal.ROUND_UP).multiply(orderSource.getTaxRate().divide(num));
            sourceCost.setTaxAmount(taxAmount.setScale(0, BigDecimal.ROUND_HALF_UP).intValue());
            sourceCostList.add(sourceCost);
        }

        return sourceCostList;
    }


    /**
     * 场景收入成本报表
     *
     * @param orderSourceCostVO
     * @param request
     * @param response
     * @throws IOException
     */
    public void export(GetOrderSourceCostVO orderSourceCostVO, HttpServletRequest request, HttpServletResponse response) throws IOException {
        QueryWrapper<OrderSourceCost> conditions = new QueryWrapper<OrderSourceCost>();
        conditions.eq("is_delete", "0");
        if (StringUtils.isNotEmpty(orderSourceCostVO.getDate())) {
            conditions.eq("verified_time", orderSourceCostVO.getDate().replace("-", ""));
        }
        if (StringUtils.isNotEmpty(orderSourceCostVO.getOrderSource())) {
            conditions.eq("order_source", orderSourceCostVO.getOrderSource());
        }

        List<OrderSourceCost> list = costMapper.selectList(conditions);
        if (CollectionUtils.isNotEmpty(list)) {
            convertSourceCostList(list);
        }
        List<OrderSourceCostExportVO> listExp = new ArrayList<OrderSourceCostExportVO>();
        for (OrderSourceCost orderSource : list) {
            OrderSourceCostExportVO costExportVO = ObjectConvertUtil.convert(orderSource, OrderSourceCostExportVO.class).get();
            listExp.add(costExportVO);
        }

        List<Map<String, Object>> mapList = listConvert(listExp);

        String fileName = "场景收入成本报表.xlsx";

        String[] title = {"结算周期", "城市", "供应商", "商户", "合作模式", "商品", "发票类型", "销售价格(￥)", "手续费(￥)", "结算价格(￥)", "税率", "平台服务费(￥)", "不含税成本(￥)", "税额", "起始日", "截止日"};
        Workbook workbook = ExcelUtil.buildWorkbook("场景收入成本", title, mapList);

        ExcelUtil.exportExcle(request, response, workbook, fileName);
    }

    /**
     * 数据转换
     *
     * @param list
     * @return
     */
    private List<Map<String, Object>> listConvert(List<OrderSourceCostExportVO> list) {
        List<Map<String, Object>> list_map = new ArrayList<Map<String, Object>>();
        try {
            for (OrderSourceCostExportVO t : list) {
                Field[] fields = t.getClass().getDeclaredFields();
                Map<String, Object> m = new LinkedHashMap<String, Object>();
                for (Field field : fields) {
                    String keyName = field.getName();
                    PropertyDescriptor pd = new PropertyDescriptor(keyName, t.getClass());
                    Method getMethod = pd.getReadMethod();// 获得getter方法
                    Object o = getMethod.invoke(t);// 执行get方法返回一个Object
                    m.put(keyName, o);
                }
                list_map.add(m);
            }
            return list_map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
